home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Language / Compiler / variables.c < prev    next >
C/C++ Source or Header  |  1990-08-16  |  21KB  |  797 lines

  1. /*
  2.  * @(#)variables.c    1.8  6/18/88
  3.  */
  4. #include "assert.h"
  5. #include "genutils.h"
  6. #include "nodes.h"
  7. #include "builtins.h"
  8. #include "regdefs.h"
  9. #include "emit.h"
  10. #include "environment.h"
  11. #include "MyParser.h"
  12. #include "flags.h"
  13. #include "trace.h"
  14. #include "system.h"
  15. #include "semantics.h"
  16.  
  17. void squirrelStringLiteral(), dumpStringLiterals();
  18. void squirrelVectorLiteral(), dumpVectorLiterals();
  19.  
  20. /*
  21.  * This file defines the variable stack.  It is used to keep track of
  22.  * partial results in the code-generation process.
  23.  *
  24.  * When code is being generated for an invocation, the target will be on top
  25.  * of the stack, and the parameters will be there in normal order, that is,
  26.  * the last parameter will be on top of the stack.
  27.  */
  28.  
  29. #define MAXVARIABLESTACKDEPTH 100
  30. Variable vStack[MAXVARIABLESTACKDEPTH];
  31. VariablePtr vStackTop = &vStack[-1];
  32.  
  33. extern NodePtr currentObject;
  34.  
  35. Boolean vEmpty()
  36. {
  37.   return(vStackTop == &vStack[-1]);
  38. }
  39.  
  40. void vPushDD(data, abcon)
  41. DD data, abcon;
  42. {
  43.   assert(vStackTop < &vStack[MAXVARIABLESTACKDEPTH]);
  44.   ++vStackTop;
  45.   vStackTop->data = data;
  46.   vStackTop->abCon = abcon;
  47. }
  48.  
  49. void vPush(v)
  50. Variable v;
  51. {
  52.   assert(vStackTop < &vStack[MAXVARIABLESTACKDEPTH]);
  53.   *++vStackTop = v;
  54. }
  55.  
  56. Boolean isPop(d)
  57. DD d;
  58. {
  59.   return(d.kind == DD_Address && d.value.address.autoIncrement);
  60. }
  61.  
  62. Boolean isSameDD(val, var)
  63. DD val, var;
  64. {
  65.   return(val.kind == var.kind && val.value.id == var.value.id ||
  66.      (val.kind == DD_Address && var.kind == DD_Address &&
  67.       val.value.address.base == var.value.address.base &&
  68.       val.value.address.hasIndex == var.value.address.hasIndex &&
  69.       (!val.value.address.hasIndex ||
  70.         val.value.address.indexReg == var.value.address.indexReg) &&
  71.       val.value.address.offset == var.value.address.offset &&
  72.       !val.value.address.autoIncrement &&
  73.       !val.value.address.autoDecrement &&
  74.       !var.value.address.autoIncrement &&
  75.       !var.value.address.autoDecrement) ||
  76.      (val.kind == DD_Address && var.kind == DD_Address &&
  77.       val.value.address.base == var.value.address.base &&
  78.       !val.value.address.hasIndex && !var.value.address.hasIndex &&
  79.       val.value.address.offset == 0 && var.value.address.offset == 0 &&
  80.       val.value.address.autoIncrement &&
  81.       var.value.address.autoDecrement));
  82. }
  83.   
  84. Boolean isNextAddress(data, abCon)
  85. DD data, abCon;
  86. {
  87.   if (data.kind != DD_Address || abCon.kind != DD_Address) return(FALSE);
  88.   if (data.value.address.autoIncrement && abCon.value.address.autoIncrement ||
  89.       data.value.address.autoDecrement && abCon.value.address.autoDecrement)
  90.     return(TRUE);
  91.   return((data .value.address.base == Register &&
  92.       abCon.value.address.base == Register &&
  93.       abCon.value.address.offset == data .value.address.offset+1) ||
  94.      (data .value.address.base == abCon.value.address.base &&
  95.       abCon.value.address.offset == data .value.address.offset+4));
  96. }
  97.  
  98. DD nextAddress(d)
  99. DD d;
  100. {
  101.   DD result;
  102.   result = d;
  103.   if (result.value.address.autoIncrement||result.value.address.autoDecrement)
  104.     return (result);
  105.   if (d.value.address.base == Register) {
  106.     assert(result.value.address.offset <= 15);    /* TODO this should be last 
  107.                                allocatable register - 1 */
  108.     result.value.address.offset ++;
  109.   } else {
  110.     result.value.address.offset += 4;
  111.     result.value.address.baseIsTemporary = FALSE;
  112.     result.value.address.indexIsTemporary = FALSE;
  113.   }
  114.   return(result);
  115. }
  116.  
  117. void vPushValue(p, c)
  118. NodePtr p;
  119. Context c;
  120. {
  121.   Variable result;
  122.   result.data = nullDD;
  123.   result.abCon = nullDD;
  124.   switch (p->tag) {
  125.     case P_BUILTINLIT:
  126.       vPushValue(refToBuiltinFromToken(B_IT, p->b.builtinlit.whichType), c);
  127.       break;
  128.     case P_NILLIT:
  129.       result.data = nilDD;
  130.       result.abCon = nilDD;
  131.       vPush(result);
  132.       break;
  133.     case P_CHARLIT:
  134.       result.data.kind = DD_Manifest;
  135.       result.data.value.manifest = (int)p->b.charlit.string[0];
  136.       result.abCon = buildConCon(CHARACTERINDEX);
  137.       vPush(result);
  138.       break;
  139.     case P_BOOLLIT:
  140.       result.data.kind = DD_Manifest;
  141.       result.data.value.manifest = p->b.boollit.value;
  142.       result.abCon = buildConCon(BOOLEANINDEX);
  143.       vPush(result);
  144.       break;
  145.     case P_REALLIT:
  146.       result.data.kind = DD_RealManifest;
  147.       result.data.value.realmanifest = p->b.reallit.string;
  148.       result.abCon = buildConCon(REALINDEX);
  149.       vPush(result);
  150.       break;
  151.     case P_INTLIT:
  152.       result.data.kind = DD_Manifest;
  153.       result.data.value.manifest = atoi(p->b.intlit.string);
  154.       result.abCon = buildConCon(INTEGERINDEX);
  155.       vPush(result);
  156.       break;
  157.     case P_STRINGLIT:
  158.       result.data.kind = DD_Label;
  159.       result.data.value.label = nextLabelNumber++;
  160.       result.abCon = buildConCon(STRINGINDEX);
  161.       squirrelStringLiteral(result.data.value.label, p->b.stringlit.string);
  162.       vPush(result);
  163.       break;
  164.     case P_GLOBALREF:
  165.       resolveGlobal(p, (ValuePtr) NULL);
  166.       vPushValue(p->b.globalref.value, c);
  167.       break;
  168.     case P_ATLIT:
  169.       /*
  170.        * When we find an atlit as the value of some symbol, it is a reference
  171.        * to a particular object that was created at compile time.
  172.        */
  173.       result.abCon = buildConCon(SIGNATUREINDEX);
  174.       result.data.kind = DD_OIDToCodePtr;
  175.       result.data.value.id = p->b.atlit.id;
  176.       ensureGenerate(p->b.atlit.id);
  177.       vPush(result);
  178.       break;
  179.     case P_OBLIT:
  180.       /*
  181.        * When we find an oblit as the value of some symbol, it is either a
  182.        * reference to a particular object that was created at compile time,
  183.        * or a reference to self.
  184.        */
  185.       if (p == currentObject) {
  186.     result.abCon = buildAbConFromObject(p);
  187.     result.data.kind = DD_Self;
  188.       } else {
  189.     result.abCon = buildAbConFromObject(p);
  190.     assert(p->b.oblit.id != 0);
  191.     result.data.kind = DD_OIDToODP;
  192.     result.data.value.id = p->b.oblit.id;
  193.       }
  194.       vPush(result);
  195.       break;
  196.     default:
  197.       assert(FALSE);
  198.   }
  199. }
  200.  
  201. void vPushOwnName(q)
  202. NodePtr q;
  203. {
  204.   NodePtr itsName;
  205.   assert(q->tag == P_OBLIT);
  206.   itsName = Construct(P_STRINGLIT, 0);
  207.   itsName->b.stringlit.string = ST_SymbolName(q->b.oblit.name->b.symdef.symbol);
  208.   vPushValue(itsName, anyContext);
  209.   FreeNode(itsName);
  210. }
  211.  
  212. void vPushOwnType(q)
  213. NodePtr q;
  214. {
  215.   assert(q->tag == P_OBLIT);
  216.   assert(q->b.oblit.myat != NN);
  217.   vPushValue(q->b.oblit.myat, anyContext);
  218. }
  219.  
  220. void vPushVariable(st)
  221. Symbol st;
  222. {
  223.   Variable v;
  224.   NodePtr ct;
  225.   
  226.   /*
  227.    * Push the address of the thing.
  228.    */
  229.   v.data.kind = DD_Address;
  230.   v.data.value.address = st->v.address;
  231.   
  232.   if (st->value.CTinfo != NULL) {
  233.     v.abCon = buildAbCon(getID(st->value.ATinfo),getCodeID(st->value.CTinfo));
  234.   } else {
  235.     ct = resolveToCTOrAT(st->value.ATinfo);
  236.     if (ct->tag == P_OBLIT) {
  237.       v.abCon = buildAbCon(getID(st->value.ATinfo), getCodeOID(ct));
  238.     } else {
  239.       v.abCon = nextAddress(v.data);
  240.       setDDAbstractType(v.abCon, getID(st->value.ATinfo));
  241.     }
  242.   }
  243.   assert(vStackTop < &vStack[MAXVARIABLESTACKDEPTH]);
  244.   *++vStackTop = v;
  245. }
  246.  
  247. Boolean hasARealValue(st)
  248. register Symbol st;
  249. {
  250.   register NodePtr ob;
  251.   if (st->isSelf) {
  252.     assert(st->value.value != NN);
  253.     return(TRUE);
  254.   } else if (st->value.value == NN) {
  255.     return (FALSE);
  256.   } else {
  257.     ob = st->value.value;
  258.     if (ob->tag == P_GLOBALREF) {
  259.       return(TRUE);
  260.     } else if (ob->tag == P_ATLIT || ob->tag == P_OBLIT) {
  261.       if (ob->b.oblit.f.writeSeparately) {
  262.     assert(ob->b.atlit.id != 0);
  263.     return(TRUE);
  264.       } else {
  265.     return(FALSE);
  266.       }
  267.     } else {
  268.       assert(FALSE);
  269.       /*NOTREACHED*/
  270.     }
  271.   }
  272. }
  273.  
  274. DD vGetSymbolAbCon(st, data)
  275. Symbol st;
  276. DD data;
  277. {
  278.   DD abcon;
  279.   NodePtr ct;
  280.   if (st->value.CTinfo != NULL) {
  281.     abcon = buildAbCon(getID(st->value.ATinfo), getCodeID(st->value.CTinfo));
  282.   } else {
  283.     ct = resolveToCTOrAT(st->value.ATinfo);
  284.     if (ct->tag == P_OBLIT) {
  285.       abcon = buildAbCon(getID(st->value.ATinfo), getCodeOID(ct));
  286.     } else {
  287.       abcon = nextAddress(data);
  288.       setDDAbstractType(abcon, getID(st->value.ATinfo));
  289.     }
  290.   }
  291.   return(abcon);
  292. }
  293.  
  294. void vPushSymbol(st, c)
  295. Symbol st;
  296. Context c;
  297. {
  298.   Variable v;
  299.   
  300.   /*
  301.    * What this does is look at the value field of the reference and do the
  302.    * right thing.  If the value is known then that value is used at compile
  303.    * time, which implies that the concrete type must be known as well.  If it
  304.    * is not known, then if the concrete type is known we push a Variable with
  305.    * the Ab/Con set to a manifest and the value to the address of the
  306.    * symbol, otherwise both the value and the Ab/Con are addresses.
  307.    */
  308.   if (hasARealValue(st)) {
  309.     vPushValue(st->value.value, c);
  310.   } else {
  311.     v.data.kind = DD_Address;
  312.     v.data.value.address = st->v.address;
  313.     v.abCon = vGetSymbolAbCon(st, v.data);
  314.     assert(vStackTop < &vStack[MAXVARIABLESTACKDEPTH]);
  315.     *++vStackTop = v;
  316.   }
  317. }
  318.  
  319. void vSwap()
  320. {
  321.   Variable v;
  322.   assert(vStackTop >= &vStack[1]);
  323.   v = *vStackTop;
  324.   *vStackTop = *(vStackTop - 1);
  325.   *(vStackTop - 1) = v;
  326. }
  327.  
  328. Variable vPop()
  329. {
  330.   assert(vStackTop >= &vStack[0]);
  331.   return(*vStackTop--);
  332. }
  333.  
  334. void vDiscard()
  335. {
  336.   assert(vStackTop >= &vStack[0]);
  337.   freeDD(vStackTop->data);
  338.   freeDD(vStackTop->abCon);
  339.   vStackTop --;
  340. }
  341.   
  342. /*
  343.  * Discard the dd n from the top.  To discard the top one use vDiscardN(0);
  344.  */
  345. void vDiscardN(n)
  346. int n;
  347. {
  348.   register int i;
  349.   assert(vStackTop >= &vStack[n]);
  350.   freeDD((vStackTop - n)->data);
  351.   freeDD((vStackTop - n)->abCon);
  352.   for (i = n; i > 0; i--) {
  353.     *(vStackTop - i) = *(vStackTop - i + 1);
  354.   }
  355.   vStackTop --;
  356. }
  357.   
  358. /*
  359.  * Peek at the dd n from the top.  To get the top one use vPeek(0);
  360.  */
  361. Variable *vPeek(n)
  362. int n;
  363. {
  364.   assert(vStackTop >= &vStack[n]);
  365.   return(vStackTop - (n));
  366. }
  367.  
  368. Variable vTop()
  369. {
  370.   assert(vStackTop >= &vStack[0]);
  371.   return(*vStackTop);
  372. }
  373.  
  374. DD vPopData()
  375. {
  376.   assert(vStackTop >= &vStack[0]);
  377.   return((*vStackTop--).data);
  378. }
  379.  
  380. DD vPopAbCon()
  381. {
  382.   assert(vStackTop >= &vStack[0]);
  383.   return((*vStackTop--).abCon);
  384. }
  385.  
  386. DD vTopData()
  387. {
  388.   assert(vStackTop >= &vStack[0]);
  389.   return((*vStackTop).data);
  390. }
  391.  
  392. DD vTopAbCon()
  393. {
  394.   assert(vStackTop >= &vStack[0]);
  395.   return((*vStackTop).abCon);
  396. }
  397.  
  398. void ddGenerateAssign(vardata, varabcon, valdata, valabcon)
  399. DD vardata, varabcon, valdata, valabcon;
  400. {
  401.   Boolean doFunnyAbCon = FALSE;
  402.   IFTRACE(assign, 1) {
  403.     fprintf(stdout, "ddGenerateAssign:\n");
  404.     fprintf(stdout, "vardata == "); displayDD(stdout, vardata, '\n');
  405.     fprintf(stdout, "varabcon == "); displayDD(stdout, varabcon, '\n');
  406.     fprintf(stdout, "valdata == "); displayDD(stdout, valdata, '\n');
  407.     fprintf(stdout, "valabcon == "); displayDD(stdout, valabcon, '\n');
  408.     fprintf(stdout, "==> ");
  409.   }
  410.   if (isSameDD(valdata,  vardata) && isSameDD(valabcon, varabcon)) {
  411.     IFTRACE(assign, 1) {
  412.       fprintf(stdout, "nothing\n");
  413.     }
  414.     return;
  415.   }
  416.   if (valabcon.kind == DD_AbCon && getDDAbstractType(varabcon) != (OID)0xff000000)
  417.     setDDAbstractType(valabcon, getDDAbstractType(varabcon));
  418.  
  419.   if (vardata.kind == DD_Address && varabcon.kind == DD_Address) {
  420.     doFunnyAbCon = valabcon.kind == DD_Address &&
  421.       getDDAbstractType(valabcon) != getDDAbstractType(varabcon);
  422.     if (doFunnyAbCon) {
  423.       if (vardata.value.address.autoDecrement) {
  424.     assert(varabcon.value.address.autoDecrement);
  425.     doFunnyAbCon = FALSE;
  426.       }
  427.     }
  428.       
  429.     assert(isNextAddress(vardata, varabcon));
  430.     if (valdata.kind == DD_Manifest && valabcon.kind == DD_Manifest) {
  431.       /*
  432.        * This is a case for a funny movq.
  433.        */
  434. #ifdef vax      
  435.       if (valdata.value.manifest == 0 && valabcon.value.manifest == 0) {
  436.     emit("\tclrq\t");
  437.     writeDD(vardata, '\n');
  438.     IFTRACE(assign, 1) {
  439.       fprintf(stdout, "\tclrq\t");
  440.       displayDD(stdout, vardata, '\n');
  441.     }
  442.       } else {
  443.     emit("\tmovq\t$0x%08x%08x,",
  444.       valdata.value.manifest, valabcon.value.manifest);
  445.     writeDD(vardata, '\n');
  446.     IFTRACE(assign, 1) {
  447.       fprintf(stdout, "\tmovq\t$0x%08x%08x,",
  448.         valdata.value.manifest, valabcon.value.manifest);
  449.       displayDD(stdout, vardata, '\n');
  450.     }
  451.       }
  452. #endif
  453. #ifdef sun
  454.       emitMove(valdata, vardata, 'l');
  455.       emitMove(valabcon, varabcon, 'l');
  456.       IFTRACE(assign, 1) {
  457.     fprintf(stdout, "\tmovl\t$0x%08x,", valdata.value.manifest);
  458.     displayDD(stdout, vardata, '\n');
  459.     fprintf(stdout, "\tmovl\t$0x%08x,", valabcon.value.manifest);
  460.     displayDD(stdout, varabcon, '\n');
  461.       }
  462. #endif
  463.     } else if (valdata.kind == DD_Address && valabcon.kind == DD_Address &&
  464.     isNextAddress(valdata, valabcon)) {
  465.       if (valabcon.value.address.autoIncrement) {
  466.     NodePtr ct;
  467.     DD newabcon;
  468.     ct = getBestInfoFromAbCon(valabcon);
  469.     if (getDDAbstractType(varabcon) == (OID) 0xff000000 ||
  470.         getDDAbstractType(valabcon) == (OID) 0xff000000) {
  471.       /* no sweat, we are cheating for some reason  */
  472. #ifdef vax
  473.       emitMove(valdata, vardata, 'q');
  474. #endif
  475. #ifdef sun
  476.       emitMove(valdata, vardata, 'l');
  477.       emitMove(valabcon, varabcon, 'l');
  478. #endif
  479.     } else if (ct->tag == P_OBLIT) {
  480.       /* no sweat, we know the concrete type */
  481.       newabcon = buildAbConFromObject(ct);
  482.       if (getDDAbstractType(newabcon) != getDDAbstractType(varabcon)) {
  483.         /* we know the concrete type, but we expect a different one */
  484.         emitMove(valdata, vardata, 'l');
  485.         emit(POPABCON);
  486.         TRACE0(assign, 1, POPABCON);
  487.         newabcon = buildAbCon(getDDAbstractType(varabcon), getDDConcreteType(newabcon));
  488.         emitMove(newabcon, varabcon, 'l');
  489.       } else {
  490. #ifdef vax
  491.         emitMove(valdata, vardata, 'q');
  492. #endif
  493. #ifdef sun
  494.         emitMove(valdata, vardata, 'l');
  495.         emitMove(valabcon, varabcon, 'l');
  496. #endif
  497.       }
  498.     } else {
  499.       /* we always need to do them here */
  500.       emitMove(valdata, vardata, 'l');
  501.       fixDDView(valabcon, varabcon, getDDAbstractType(varabcon), FALSE);
  502.     }
  503.       } else if (doFunnyAbCon) {
  504.     emitMove(valdata, vardata, 'l');
  505.     fixDDView(valabcon, varabcon, getDDAbstractType(varabcon), TRUE);
  506.       } else {
  507. #ifdef vax
  508.     emitMove(valdata, vardata, 'q');
  509. #endif
  510. #ifdef sun
  511.     if (vardata.value.address.autoDecrement) {
  512.       emitMove(valabcon, varabcon, 'l');
  513.       emitMove(valdata, vardata, 'l');
  514.     } else {
  515.       emitMove(valdata, vardata, 'l');
  516.       emitMove(valabcon, varabcon, 'l');
  517.     }
  518. #endif
  519.       }
  520.     } else if (vardata.value.address.autoDecrement) {
  521.       /* push, so we have to do the abCon first */
  522.       assert(!doFunnyAbCon);
  523.       assert(varabcon.value.address.autoDecrement);
  524.       if (valdata.kind == DD_PSLCondition) {
  525.     /* we need to put the value from the PSL into somewhere */
  526.     Variable v;
  527.     v.data = valdata;
  528.     v.abCon = valabcon;
  529.     vForceToTemp(&v, TS_PSL);
  530.     valdata = v.data;
  531.     valabcon = v.abCon;
  532.       }
  533.       emitMove(valabcon, varabcon, 'l');
  534.       emitMove(valdata, vardata, 'l');
  535.     } else {
  536.       /* pop or dont care, so we do the data first */
  537.       assert(!doFunnyAbCon);
  538.       if (valdata.kind == DD_Address && valdata.value.address.autoIncrement)
  539.     assert(FALSE);
  540.       emitMove(valdata, vardata, 'l');
  541.       emitMove(valabcon, varabcon, 'l');
  542.     }
  543.   } else {
  544.     /* just the data */
  545.     assert(vardata.kind == DD_Address);
  546.     assert(varabcon.kind == DD_AbCon || varabcon.kind == DD_Manifest);
  547.     emitMove(valdata, vardata, 'l');
  548.     if (isPop(valabcon)) {
  549.       emit(POPABCON);
  550.       TRACE0(assign, 1, POPABCON);
  551.     }
  552.   }
  553.   freeDD(valdata);
  554.   freeDD(valabcon);
  555. }
  556.  
  557. void ddGenerateMovqAssign(size, vardata, varabcon, valdata, valabcon)
  558. int size;
  559. DD vardata, varabcon, valdata, valabcon;
  560. {
  561.   if (size == 8 && valabcon.kind == DD_AbCon) {
  562.     /* we need to worry since we need to do a movq */
  563.     Variable auxv, *aux = &auxv;
  564.     aux->data = pusher;
  565.     aux->abCon = pusher;
  566.     setDDAbstractType(aux->abCon, getDDAbstractType(valabcon));
  567.     ddGenerateAssign(aux->data, aux->abCon, valdata, valabcon);
  568.     aux->data = popper;
  569.     aux->abCon = popper;
  570.     ddGenerateAssign(vardata, varabcon, aux->data, aux->abCon);
  571.   } else {
  572.     ddGenerateAssign(vardata, varabcon, valdata, valabcon);
  573.   }
  574. }
  575.  
  576. void vGenerateAssign()
  577. {
  578.   register VariablePtr var, val;
  579.  
  580.   assert(vStackTop >= &vStack[1]);
  581.   val = vStackTop;
  582.   var = (vStackTop - 1);
  583.   ddGenerateAssign(var->data, var->abCon, val->data, val->abCon);
  584.   (void) vPop();
  585.   (void) vPop();
  586. }
  587.  
  588. void findTemp(v, size, brand)
  589. Variable *v;
  590. int size;
  591. Brand brand;
  592. {
  593.   int registerNo, stackAddress;
  594.   registerNo = allocateReg(size / 4, brand);
  595.   if (registerNo >= 0) {
  596.     v->data = buildRegisterDD(registerNo);
  597.   } else {
  598.     stackAddress = TS_Allocate(size, brand);
  599.     v->data.kind = DD_Address;
  600.     v->data.value.address = nullAddress;
  601.     v->data.value.address.base = regs_l;
  602.     v->data.value.address.baseIsTemporary = TRUE;
  603.     v->data.value.address.offset = stackAddress;
  604.   }
  605.   if (size == 8) v->abCon = nextAddress(v->data);
  606. }
  607.  
  608. void vForceToTemp(v, which)
  609. register Variable *v;
  610. int which;
  611. {  
  612.   int registerNo, stackAddress;
  613.   DD newdata, newabcon;
  614.   NodePtr ct;
  615.  
  616.   if (! (((which & TS_Stack) &&
  617.       v->data.kind == DD_Address &&
  618.       v->data.value.address.base == regs_sp &&
  619.       v->data.value.address.autoIncrement) ||
  620.      ((which & TS_PSL) &&
  621.       v->data.kind == DD_PSLCondition) ||
  622.      ((which & TS_Self) && v->data.kind == DD_Self) ||
  623.      ((which & TS_Label) &&
  624.       v->data.kind == DD_Label))) return;
  625.  
  626.   newabcon = v->abCon;
  627.   if (newabcon.kind != DD_AbCon) {
  628.     ct = resolveOIDToCTOrAT(getDDAbstractType(newabcon));
  629.     if (ct->tag == P_OBLIT) {
  630.       newabcon = buildAbCon(getDDAbstractType(newabcon), ct->b.oblit.codeOID);
  631.     }
  632.   }
  633.   if (newabcon.kind == DD_AbCon) {
  634.     registerNo = allocateReg(1, abConToBrand(newabcon));
  635.     if (registerNo >= 0) {
  636.       newdata = buildRegisterDD(registerNo);
  637.     } else {
  638.       stackAddress = TS_Allocate(4, abConToBrand(newabcon));
  639.       newdata.kind = DD_Address;
  640.       newdata.value.address = nullAddress;
  641.       newdata.value.address.base = regs_l;
  642.       newdata.value.address.baseIsTemporary = TRUE;
  643.       newdata.value.address.offset = stackAddress;
  644.     }
  645.     ddGenerateAssign(newdata, newabcon, v->data, v->abCon);
  646.     v->data = newdata;
  647.     v->abCon = newabcon;
  648.   } else {
  649.     /* check for thing on stack, if so, put it on stack */
  650.     if (v->abCon.value.address.autoIncrement) {
  651.       registerNo = -1;
  652.     } else {
  653.       registerNo = allocateReg(2, VariableBrand);
  654.     }
  655.     if (registerNo >= 0) {
  656.       newdata = buildRegisterDD(registerNo);
  657.     } else {
  658.       stackAddress = TS_Allocate(8, VariableBrand);
  659.       newdata.kind = DD_Address;
  660.       newdata.value.address = nullAddress;
  661.       newdata.value.address.base = regs_l;
  662.       newdata.value.address.baseIsTemporary = TRUE;
  663.       newdata.value.address.offset = stackAddress;
  664.     }
  665.     newabcon = nextAddress(newdata);
  666.     setDDAbstractType(newabcon, getDDAbstractType(v->abCon));
  667.     ddGenerateAssign(newdata, newabcon, v->data, v->abCon);
  668.     v->data = newdata;
  669.     v->abCon = newabcon;
  670.   }
  671. }
  672.  
  673. typedef struct {
  674.   int         regNo;
  675.   DD         argument;
  676. } KARec, *KARecPtr;    
  677.   
  678. /*
  679.  * This one preempts all the kernel registers, assigns the given things to
  680.  * the given input registers, and claims the result register with the given
  681.  * brand.
  682.  */
  683.  
  684. /*VARARGS2*/
  685. DD preemptAndAssign(resultBrand, nArgs, firstArg)
  686. Brand resultBrand;
  687. int nArgs;
  688. KARec firstArg;
  689. {
  690.   KARecPtr args = &firstArg;
  691.   int i;
  692.   Boolean done[4];
  693.   DD d;
  694.   done[0] = done[1] = done[2] = done[3] = FALSE;
  695.   d.kind = DD_Address;
  696.   d.value.address = nullAddress;
  697.   d.value.address.base = Register;
  698.  
  699.   for (i = 0; i < nArgs; i++) {
  700.     d.value.address.offset = args[i].regNo;
  701.     if (isSameDD(args[i].argument, d)) {
  702.       done[args[i].regNo] = TRUE;
  703.     }
  704.   }
  705.   for (i = 0; i < 4; i++) {
  706.     if (!done[i]) preemptReg(i, 1);
  707.   }
  708.   for (i = 0; i < nArgs; i++) {
  709.     if (!done[args[i].regNo]) {
  710.       claimReg(args[i].regNo, 1, DataBrand);
  711.       emitMove(args[i].argument, buildRegisterDD(args[i].regNo), 'l');
  712.     }
  713.   }
  714.   for (i = 0; i < nArgs; i++) {
  715.     freeReg(args[i].regNo, 1);
  716.   }
  717.   claimReg(regs_arg1, 1, resultBrand);
  718.   return(buildRegisterDD(regs_arg1));
  719. }
  720.  
  721. void vDisplayStack()
  722. {
  723.   register VariablePtr v;
  724.   for (v = vStackTop; v >= &vStack[0]; v--) {
  725.     fprintf(stdout, "Variable stack [%d]\n  data -> ", v - &vStack[0]);
  726.     displayDD(stdout, v->data, '\n');
  727.     fprintf(stdout, "  abCon-> ");
  728.     displayDD(stdout, v->abCon, '\n');
  729.   }
  730.   fflush(stdout);
  731. }
  732.  
  733. typedef struct sStringLiteral {
  734.   int             label;
  735.   char             *string;
  736.   struct sStringLiteral    *next;
  737. } StringLiteral, *SLPtr;
  738. static SLPtr slHead = NULL;
  739.  
  740. typedef struct sVectorLiteral {
  741.   int             label;
  742.   int             elementTypeSize;
  743.   OID             vecCodeOID;
  744.   NodePtr         vector;
  745.   struct sVectorLiteral    *next;
  746. } VectorLiteral, *VLPtr;
  747. static VLPtr vlHead = NULL;
  748.  
  749. void squirrelStringLiteral(label, string)
  750. int label;
  751. char *string;
  752. {
  753.   register SLPtr s;
  754.   s = (SLPtr) malloc(sizeof(StringLiteral));
  755.   s->next = slHead;
  756.   s->label = label;
  757.   s->string = string;
  758.   slHead = s;
  759. }
  760.  
  761. void dumpStringLiterals()
  762. {
  763.   register SLPtr s;
  764.   while (slHead != NULL) {
  765.     s = slHead; 
  766.     slHead = s->next;
  767.     emitStringObject(s->string, s->label, (char *)NULL, 0);
  768.     free((char *) s);
  769.   }
  770. }
  771.  
  772. void squirrelVectorLiteral(label, vector, elementTypeSize, vecCodeOID)
  773. int label;
  774. NodePtr vector;
  775. int elementTypeSize;
  776. OID vecCodeOID;
  777. {
  778.   register VLPtr s;
  779.   s = (VLPtr) malloc(sizeof(VectorLiteral));
  780.   s->next = vlHead;
  781.   s->label = label;
  782.   s->elementTypeSize = elementTypeSize;
  783.   s->vecCodeOID = vecCodeOID;
  784.   s->vector = vector;
  785.   vlHead = s;
  786. }
  787. void dumpVectorLiterals()
  788. {
  789.   register VLPtr s;
  790.   while (vlHead != NULL) {
  791.     s = vlHead; 
  792.     vlHead = s->next;
  793.     emitVectorObject(s->vector, s->label, s->elementTypeSize, s->vecCodeOID);
  794.     free((char *) s);
  795.   }
  796. }
  797.